package com.fingard.dsp.bank.directbank.cib01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.dsp.task.command.SyncReceipt;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.ZipHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import netbank.firm.service.FileService;
import org.springframework.stereotype.Component;

import java.io.File;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by aaron on 2020/6/9.
 */
@Component("CIB01ReceiptPro")
public class CIB01ReceiptPro extends CIB01Base implements IReceiptPro{
    @Override
    public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        String qryDay = Format.Date10Format.format(pOneDay);
        //回单数据保存类，分区分表
        ReceiptDataHelper receiptHelper = null;
        List<String> fileList=new ArrayList<String>();
        try {
            receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);
            //查询回单信息
            writeInfoLog(String.format("开始查询账号【%s】在日期【%s】的回单信息", pReqReceipt.actNum, qryDay));
            qryReceiptInfo(receiptHelper, pReqReceipt, pOneDay);

            List<String> istNbrList = receiptHelper.getIstNbrList(pReqReceipt.actNum, pOneDay);
            if (istNbrList == null || istNbrList.size() == 0) {
                writeInfoLog(String.format("账号【%s】在日期【%s】没有需要下载的回单", pReqReceipt.actNum, qryDay));
                return null;
            }

            //调用银行的回单生产接口生产回单，并获取下载要用的批次号
            String batchid = generatePDF(pReqReceipt.actNum, pOneDay);
            if (StringHelper.isNullOrEmpty(batchid)) {
                return null;
            }
            writeInfoLog(String.format("开始下载账号【%s】在日期【%s】的回单文件", pReqReceipt.actNum, qryDay));
            fileList= downLoadPDF(batchid);

            writeInfoLog(String.format("开始对账号【%s】在日期【%s】的回单明细和文件进行匹配", pReqReceipt.actNum, qryDay));
            if (fileList.size() != 0) {
                for (String fileName : fileList) {
                    receiptMatch(receiptHelper, pConfig, pReqReceipt, pOneDay, fileName);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            writeErrorLog(ex.getMessage());
        } finally {
            if(fileList!=null&&fileList.size()!=0){
                for (String fileName : fileList) {
                    boolean delFlag = FileHelper.deleteFileIfExists(fileName);
                    if(delFlag){
                        writeInfoLog("删除文件："+fileName+"成功");
                    }else {
                        writeErrorLog("删除文件："+fileName+"失败");
                    }
                }
            }
            receiptHelper.close();
        }
        SyncReceipt.resetDelayCounter();//同步任务重新计数延时
        return null;
    }

    private void receiptMatch(ReceiptDataHelper receiptHelper,ReceiptProConfig pConfig,ReqQryReceipt pReqReceipt, Date pOneDay,String fileName) {
        String tmpReceiptPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) +
                File.separator + "tmpReceiptDir" + File.separator + pReqReceipt.actNum + File.separator + Format.Date8Format.format(pOneDay) +StringHelper.splitFileNameAndExt(fileName)[0];
        try {
            FileHelper.mkdir(tmpReceiptPath);
            WriteBankLogLn("开始解压文件" + fileName + "至临时文件夹" + tmpReceiptPath);
            ZipHelper.unZipFiles(fileName, tmpReceiptPath);
            File tmpReceiptDir = new File(tmpReceiptPath);
            String receiptDirRelPath = pConfig.getRelativeSaveDir(reqHeader, pOneDay) + File.separator + pReqReceipt.actNum+File.separator + Format.Date10Format.format(pOneDay);

            if (tmpReceiptDir.exists() && tmpReceiptDir.listFiles().length != 0) {
                List<String> IstNbrList = receiptHelper.getIstNbrList(pReqReceipt.actNum, pOneDay);
                for (File pdfFile : tmpReceiptDir.listFiles()) {
                    String receiptNo = StringHelper.splitFileNameAndExt(pdfFile.getName())[0];
                    String pdfRelPath = receiptDirRelPath + File.separator + StringHelper.trimStartFileSp(pdfFile.getName());
                    String pdfAbsPath = pConfig.localSaveMainDir + File.separator + pdfRelPath;

                    if (IstNbrList.contains(receiptNo)) {
                        FileHelper.copyFile(pdfFile.getAbsolutePath(), pdfAbsPath);
                        //下载回单文件
                        if (FileHelper.existFile(pdfAbsPath)) {
                            ReceiptData receiptData = receiptHelper.loadFromDbByIstNbr(pReqReceipt.actNum, receiptNo);
                            int rowAff = receiptHelper.updateDownState(pReqReceipt.actNum, receiptData.istNbr, pdfRelPath, pdfFile.getName(), "2");
                            writeInfoLog(String.format("回单编号【%s】与回单文件【%s】匹配成功\n文件保存地址：%s",pReqReceipt.actNum,pdfFile.getName(),pdfAbsPath));
                            writeInfoLog("影响数据库行数："+rowAff);
                        } else {
                            writeErrorLog(String.format("回单编号【%s】与回单文件【%s】匹配失败",pReqReceipt.actNum,pdfFile.getName()));
                        }
                    }
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
            writeErrorLog(ex.getMessage());
        }finally {
            boolean delFlag =FileHelper.deleteRecursive(tmpReceiptPath);
            if(delFlag){
                writeInfoLog("删除文件："+tmpReceiptPath+"成功");
            }else {
                writeErrorLog("删除文件："+tmpReceiptPath+"失败");
            }
        }

    }

    private List<String> downLoadPDF(String batchid) {
        List<String> fileNameList =new ArrayList<String>();
        int page =0;
        boolean hasNextPage;
        try {
            do {
                //1.2 同步电子回单
                page++;
                hasNextPage= false;
                CIB01Header header2 = new CIB01Header();
                XmlTextWriter xmlWriter2 = new XmlTextWriter();//发银行报文的XML对象
                writeHeaderReceipt(xmlWriter2, header2);
                xmlWriter2.writeStartElement("SECURITIES_MSGSRQV1");
                xmlWriter2.writeStartElement(CIB01TransType.Receipt);
                xmlWriter2.writeElementString("TRNUID", getQryTransID());//流水号
                xmlWriter2.writeElementAttribute("RQBODY", "PAGE", page + "");
                xmlWriter2.writeElementString("CLT_REF_NO", batchid);//批次号
                xmlWriter2.writeEndElement();
                xmlWriter2.writeEndElement();
                xmlWriter2.writeEndElement();
                xmlWriter2.writeEndDocument();
                String[] tmpStrRet2 = sendToBankReceipt(xmlWriter2.toXmlString());
                if (tmpStrRet2[0].length() == 0) {
                    StringBuilder tmpSbMsg2 = new StringBuilder();
                    XmlTextReader tmpBkReader2 = loadBankRespXmlReader(tmpStrRet2[1], tmpSbMsg2);
                    if (tmpBkReader2 != null) {
                        String trspCod = tmpBkReader2.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/CODE");
                        String trspMsg = tmpBkReader2.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");
                        if ("0".equals(trspCod)) {
                            String rspCod = tmpBkReader2.getFirstText("/FOX/SECURITIES_MSGSRSV1/ASYNRECEIPTINFOTRNRS/STATUS/CODE");
                            String rspMsg = tmpBkReader2.getFirstText("/FOX/SECURITIES_MSGSRSV1/ASYNRECEIPTINFOTRNRS/STATUS/MESSAGE");

                            if ("0".equals(rspCod)) {
                                //是否下一页标识 Y：有 N：无
                                tmpBkReader2.read("/FOX/SECURITIES_MSGSRSV1/ASYNRECEIPTINFOTRNRS/RSBODY");
                                XElement readXElement2 = tmpBkReader2.readedXElement;
                                String more = readXElement2.hashMapAttributes.get("MORE");
                                if ("Y".equals(more.trim())) {
                                    hasNextPage = true;
                                }

                                ArrayList<XElement> list = readXElement2.getChildList("CONTENT");

                                for (int i = 0; i < list.size(); i++) {
                                    //XElement readXElement = tmpBkReader2.readedXElement;
                                    //文件名
                                    String fileName = list.get(i).getSingleTextNotNull("FILE_NAME");
                                    //文件id
                                    String fileId = list.get(i).getSingleTextNotNull("FILE_ID");
                                    FileService service = new FileService();
                                    String filePath2 = service.downloadFile(fileName, fileId);
                                    if(StringHelper.hasAnyChar(filePath2)) {
                                        fileNameList.add(filePath2);
                                        writeInfoLog(String.format("文件名【%s】文件id【%s】对应的回单压缩包下载成功,文件路径为:【%s】",fileName,fileId,filePath2));
                                    }else {
                                        writeErrorLog(String.format("文件名【%s】文件id【%s】对应的回单压缩包下载失败",fileName,fileId));
                                    }
                                }
                            } else {
                                writeErrorLog(rspMsg);
                            }
                        } else {
                            writeErrorLog(trspMsg);
                        }
                    } else {
                        writeErrorLog(tmpSbMsg2.toString());
                    }
                } else {
                    writeErrorLog(tmpStrRet2[1]);
                }
            }while (hasNextPage);
        } catch (Exception ex) {
            ex.printStackTrace();
            writeErrorLog(ex.getMessage());
        }
        return fileNameList;
    }

    private String generatePDF(String actNum, Date pOneDay) {
        String batchId="";
        try {
            CIB01Header header = new CIB01Header();
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            writeHeaderReceipt(xmlWriter, header);
            xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
            xmlWriter.writeStartElement("ELECTRONICRECEIPTTRNRQ");
            xmlWriter.writeElementString("TRNUID", getQryTransID());
            xmlWriter.writeStartElement("RQBODY");
            xmlWriter.writeElementString("RECEIPT_TYPE", "01");
            xmlWriter.writeElementString("ACCTID", actNum);
            xmlWriter.writeElementString("RECEIPTDATE", Format.Date10Format.format(pOneDay));
            xmlWriter.writeEndElement();
            xmlWriter.writeEndElement();
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();
            FGBiz.logTrace.info("发送银行的报文："+xmlWriter.toXmlString());
            String[] tmpStrRet = sendToBankReceipt(xmlWriter.toXmlString());
            FGBiz.logTrace.info("银行返回的报文："+tmpStrRet[1]);

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String trspcod = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/CODE");
                    String trspmsg = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");
                    if ("0".equals(trspcod)) {
                        String rspcod = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/ELECTRONICRECEIPTTRNRS/STATUS/CODE");
                        String rspmsg = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/ELECTRONICRECEIPTTRNRS/STATUS/MESSAGE");
                        if ("0".equals(rspcod)) {
                            String status = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/ELECTRONICRECEIPTTRNRS/RSBODY/STATUS");//处理结果状态
                            if ("3".equals(status)) {//处理失败，重新发送
                                writeErrorLog("处理失败");
                            } else {
                                //获取批次号
                                batchId = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/ELECTRONICRECEIPTTRNRS/RSBODY/CLT_REF_NO");
                                writeErrorLog("批次号" + batchId + "回单指令状态(0:未处理，1:处理中，2:已处理)为" + status + ",后台定时器处理中");
                            }
                        } else if("2002".equals(rspcod)){
                            int index =rspmsg.indexOf("已存在任务,批次号为:");
                            if(index>=0){
                                return rspmsg.substring(index+"已存在任务,批次号为:".length());
                            }
                            writeInfoLog(rspmsg);
                        }else {
                            writeErrorLog(rspmsg);
                        }
                    } else {
                        writeErrorLog(trspmsg);
                    }
                } else {
                    writeErrorLog(tmpSbMsg.toString());
                }
            } else {
                writeErrorLog(tmpStrRet[1]);
            }

        } catch (Exception e)
        {
            e.printStackTrace();
            writeErrorLog(e.getMessage());
        }
        return batchId;
    }

    private void qryReceiptInfo(ReceiptDataHelper receiptHelper, ReqQryReceipt pReqReceipt, Date pOneDay) {
        boolean hasNextPage = false;
        int pageIndex = 0;
        try {
            do {
                pageIndex++;
                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeCommonHeader(xmlWriter);
                xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
                xmlWriter.writeStartElement(CIB01TransType.Q7516);
                xmlWriter.writeElementString("TRNUID", getQryTransID());//p_req7516.reqHeader.transSeqID);
                xmlWriter.writeStartElement("SCUSTSTMTRQ");
                xmlWriter.writeStartElement("ACCTFROM");
                xmlWriter.writeElementString("ACCTID", pReqReceipt.actNum);
                xmlWriter.writeEndElement();
                xmlWriter.writeStartElement("INCTRAN");
                xmlWriter.writeElementString("DTSTART", Format.Date10Format.format(pOneDay));
                xmlWriter.writeElementString("DTEND", Format.Date10Format.format(pOneDay));
                xmlWriter.writeElementString("PAGE", pageIndex + "");
                xmlWriter.writeEndDocument();
                String xmlSend = writeContentLength(xmlWriter);
                FGBiz.logTrace.info("发送银行的报文:"+this.getLogCode(),xmlSend);
                String[] tmpStrRet = sendToBank(xmlSend);
                FGBiz.logTrace.info("银行返回的报文:"+this.getLogCode(),tmpStrRet[1]);
                String returnXml = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<FOX>"), tmpStrRet[1].length());
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(returnXml, tmpSbMsg);
                    if (tmpBkReader != null) {
                        String retCode = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/SCUSTSTMTTRNRS/STATUS/CODE");
                        String retServerity = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/SCUSTSTMTTRNRS/STATUS/SEVERITY");
                        if ("0".equals(retCode)) {
                            if(!tmpBkReader.read("/FOX/SECURITIES_MSGSRSV1/SCUSTSTMTTRNRS/SCUSTSTMTRS/TRANLIST")){
                                {
                                    writeInfoLog(String.format("账号【%s】在日期【%s】没有交易记录",pReqReceipt.actNum,Format.Date10Format.format(pOneDay)));
                                }
                            }
                            hasNextPage = "Y".equals(tmpBkReader.readedXElement.getAttrValue("MORE"))?true:false;
                            if(tmpBkReader.readedXElement.getChildList("STMTTRN")!=null) {
                                for (XElement tranXElement : tmpBkReader.readedXElement.getChildList("STMTTRN")) {
                                    ReceiptData receiptData = new ReceiptData();
                                    receiptData.ownAct = pReqReceipt.actNum;
                                    receiptData.cur = pReqReceipt.actCur;
                                    receiptData.bank = "309";
                                    receiptData.srcSys = this.bankFront.bankCode;
                                    receiptData.istNbr = tranXElement.getSingleTextNotNull("ATTACHINFO").trim();
                                    receiptData.receiptNo = receiptData.istNbr;
                                    String dealDate = tranXElement.getSingleText("DTACCT").substring(0, 10);
                                    receiptData.busDate = Integer.valueOf(dealDate.replace("-",""));
                                    // #start 提取摘要、备注，摘要和备注中有一个字段含有对账码，通过提取方法获取对账码
                                    receiptData.oppActNum = tranXElement.getSingleTextNotNull("CORRELATE_ACCTID").trim();
                                    receiptData.oppActName = tranXElement.getSingleTextNotNull("CORRELATE_NAME").trim();
                                    // #end
                                    // #start "发生额、余额、借贷标志 0-借 1-贷"
                                    String dealMoney = tranXElement.getSingleText("TRNAMT");//交易金额
                                    String loanSign = tranXElement.getSingleText("TRNTYPE");//借贷标志
                                    if (loanSign.equals("DEBIT")) {
                                        if (dealMoney.indexOf("-") < 0) {//借正，正常业务
                                            receiptData.moneyWay = "1";
                                        } else {//借负，银行退票,表示收入
                                            dealMoney = dealMoney.replace("-", "");
                                            receiptData.moneyWay = "2";//借贷表示置为贷，表示收入
                                        }
                                    } else {
                                        if (dealMoney.indexOf("-") < 0) {//贷正，正常业务
                                            receiptData.moneyWay = "2";
                                        } else {//贷负，目前应该没有这种业务，按照正常的程序逻辑做一下处理
                                            dealMoney = dealMoney.replace("-", "");
                                            receiptData.moneyWay = "1";//借贷表示置为借，表示支出
                                        }
                                    }
                                    receiptData.amount = new BigDecimal(dealMoney);
                                    // #end
                                    int inRe = receiptHelper.insertIfNotExist(receiptData,true);
                                    if (inRe == 1) {
                                        writeInfoLog(String.format("账号【%s】日期【%s】回单编号【%s】写入数据库",pReqReceipt.actNum,Format.Date10Format.format(pOneDay),receiptData.istNbr)
                                                +",影响行数：" + inRe);
                                    } else if (inRe == 0) {
                                        writeInfoLog(String.format("账号【%s】日期【%s】回单编号【%s】更新数据库",pReqReceipt.actNum,Format.Date10Format.format(pOneDay),receiptData.istNbr)
                                                +",影响行数：" + inRe);
                                    }
                                }
                            }

                            //当没有明细记录时的返回结果
                        } else if ("6421".equals(retCode) && "INFO".equals(retServerity)) {
                            hasNextPage = false;
                        } else {
                            throw new Exception("查询明细失败，银行返回信息：" + tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/SCUSTSTMTTRNRS/STATUS/MESSAGE"));
                        }
                    } else {
                        throw new Exception(tmpSbMsg.toString());
                    }
                } else {
                    throw new Exception(tmpStrRet[1]);
                }
            } while (hasNextPage);
        }catch (Exception ex){
            ex.printStackTrace();
            writeErrorLog(ex.getMessage());

        }
    }


    public void writeInfoLog(String msg){
        WriteBankLogLn(msg);
        FGBiz.logTrace.info(this.getLogCode(), msg);
    }

    public void writeErrorLog(String msg){
        WriteBankLogLn(msg);
        FGBiz.logTrace.error(this.getLogCode(), msg);
    }
}
